import javax.swing.JOptionPane;
/**
 * Classe que representa uma MT
 */

public class MaquinaTuring {
    
    Estado[] estados;
    char[] fita;
    int quant, idFita, estadoAtual, aux, estadoAnt, idFitaAnt;
    
    /**
     * Construtor sem parametros
     * Cria um arranjo de estados com tamanho 20
     * Um arranjo de caracteres de tamanho 13
     * Seta o atributo quantidade para 0
     * Seta o atributo de identificaçao da fita para 1
     * Seta o atributo de estado atual para 0
     * Chama o metodo que preenche o arranjo de caracteres (fita)
     */
    public MaquinaTuring(){
        estados = new Estado[20];
        fita = new char[13];
        quant = 0;
        idFita = 1;
        estadoAtual = 0;
        preencherFita();
    }
    /**
     * Metodo responsavel pela verificacao das transiçoes e estados da palavra 
     * inserida e dos estados e transiçoes inseridas pelo usuario
     * @return True se a palavra coincide com os estados e transiçoes inseridas
     * False se a palavra nao coincide
     */
    public boolean verificar(){
        estadoAnt = estadoAtual;
        idFitaAnt = idFita;
        System.out.print("Estado Atual: " + estados[estadoAtual].getNome());
        aux = 0;
        boolean achou = false;        
        
        while(!achou){
            if(!(aux >= estados[estadoAtual].transitions.getQuant())){
                if(fita[idFita] == estados[estadoAtual].transitions.getTransition(aux).getSimbolo()){
                    System.out.print(" Leu: " + fita[idFita]);
                    fita[idFita] = estados[estadoAtual].transitions.getTransition(aux).getSimbGravar();
                    System.out.print(" Gravou: " + fita[idFita]);
                    char movimento = estados[estadoAtual].transitions.getTransition(aux).getMovimento();
                    System.out.print(" Movimentou para a " + movimento);                

                    if(movimento == 'D')
                        incrementeFita();
                    else
                        decrementeFita();

                    estadoAtual = estados[estadoAtual].transitions.getTransition(aux).getDestino();
                    System.out.println(" Foi para o Estado: " + estados[estadoAtual].getNome());
                    achou = true;
                } else {
                    aux++;
                }
            } else {
                JOptionPane.showMessageDialog(null, "Palavra Inválida");
                estadoAtual = 0;
                idFita = 1;
                achou = true;
                return achou;
            }
        }
        
        if(estados[estadoAtual].getTipo() == 'F' || estados[estadoAtual].getTipo() == 'f'){
            System.out.println("A palavra foi aceita");
            JOptionPane.showMessageDialog(null, "Palavra Aceita");
            estadoAtual = 0;
            idFita = 1;
            preencherFita();
            return true;
        }
        return false;
    }
    /**
     * Adiciona um esta ao arranjo do tipo estados
     * @param e Objeto do tipo Estado
     */
    public void addEstado(Estado e){
        estados[quant] = e;
        quant++;
    }
    /**
     * Adiciona um transicao ao arranjo do tipo estados
     * @param idEstado Identificaçao do estado
     * @param t Objeto do tipo Estado
     */
    public void addTransition(int idEstado, Transicoes t){
        estados[idEstado].transitions.addTransition(t);
    }
    /**
     * Remove um Estado do arranjo de estados
     * @param id identificaçao
     * @return False se quantidade igual a 0 ou id maior que quantidade
     * True se a remoçao for realizada com sucesso
     */
    public boolean removerEstado(int id){
        if(quant == 0 || id >= quant){
            return false;
        }
        for (int i = id; i < quant-1; i++) {
            estados[i] = estados[i+1];                
        }
        quant--;
        return true;
    }
    /**
     * Remove uma Transicao da lista de estados
     * @param idEstado Identificaçao do estado
     * @param idTrans Identificaçao da transiçao
     * @return False se quantidade igual a 0 ou id maior que quantidade
     * True se a remoçao for realizada com sucesso
     */
    public boolean removerTransition(int idEstado, int idTrans){
         if(quant == 0 || idEstado >= quant){
            return false;
        } 
        
         estados[idEstado].transitions.removerTransition(idTrans);
            return true;
    }
    /**
     * Metodo que preenche o arranjo de caracteres (fita)
     */
    public void preencherFita(){
        int i = 0;
        while(i < fita.length){
            fita[i] = '$';
            i++;
        }
    }
    /**
     * Metodo que adiciona uma palavra na fita
     * @param palavra caracter a ser adicionado na fita
     */
    public void addPalavraFita(String palavra){
        int i = 1;
        while(i <= palavra.length()){
            fita[i] = palavra.charAt(i-1);
            i++;
        }
    }
    /**
     * Incrementa a fita
     */
    public void incrementeFita(){
        idFita++;
    }
    /**
     * Decrementa a fita
     */
    public void decrementeFita(){
        idFita--;
    }
    /**
     * imprime os valores do arranjo de caracteres (fita) na saida padrao
     */
    public void imprimitFita(){
        for (int i = 0; i < fita.length; i++) {
            System.out.print(fita[i]);            
        }
    }
    /**
     * Lista as transiçoes de um determinado estado
     * @param idEstado identificaçao do Estado
     */
    public void transicoesEstado(int idEstado){
        estados[idEstado].transitions.listarTransitions();
    }
    
}
